home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Environments
/
PowerLisp 2.01
/
Supplemental Documentation
/
Documentation
/
Chapter 21. Streams
< prev
next >
Wrap
Text File
|
1995-03-27
|
25KB
|
612 lines
Common Lisp the Language, 2nd Edition
-------------------------------------------------------------------------------
21. Streams
Streams are objects that serve as sources or sinks of data. Character streams
produce or absorb characters; binary streams produce or absorb integers. The
normal action of a Common Lisp system is to read characters from a character
input stream, parse the characters as representations of Common Lisp data
objects, evaluate each object (as a form) as it is read, and print
representations of the results of evaluation to an output character stream.
Typically streams are connected to files or to an interactive terminal.
Streams, being Lisp objects, serve as the ambassadors of external devices by
which input/output is accomplished.
A stream, whether a character stream or a binary stream, may be input-only,
output-only, or bidirectional. What operations may be performed on a stream
depends on which of the six types of stream it is.
-------------------------------------------------------------------------------
* Standard Streams
* Creating New Streams
* Operations on Streams
-------------------------------------------------------------------------------
21.1. Standard Streams
There are several variables whose values are streams used by many functions in
the Lisp system. These variables and their uses are listed here. By convention,
variables that are expected to hold a stream capable of input have names ending
with -input, and variables that are expected to hold a stream capable of output
have names ending with -output. Variables expected to hold a bidirectional
stream have names ending with -io.
[Variable]
*standard-input*
In the normal Lisp top-level loop, input is read from *standard-input* (that
is, whatever stream is the value of the global variable *standard-input*). Many
input functions, including read and read-char, take a stream argument that
defaults to *standard-input*.
[Variable]
*standard-output*
In the normal Lisp top-level loop, output is sent to *standard-output* (that
is, whatever stream is the value of the global variable *standard-output*).
Many output functions, including print and write-char, take a stream argument
that defaults to *standard-output*.
[Variable]
*error-output*
The value of *error-output* is a stream to which error messages should be sent.
Normally this is the same as *standard-output*, but *standard-output* might be
bound to a file and *error-output* left going to the terminal or to a separate
file of error messages.
[Variable]
*query-io*
The value of *query-io* is a stream to be used when asking questions of the
user. The question should be output to this stream, and the answer read from
it. When the normal input to a program may be coming from a file, questions
such as ``Do you really want to delete all of the files in your directory?''
should nevertheless be sent directly to the user; and the answer should come
from the user, not from the data file. For such purposes *query-io* should be
used instead of *standard-input* and *standard-output*. *query-io* is used by
such functions as yes-or-no-p.
[Variable]
*debug-io*
The value of *debug-io* is a stream to be used for interactive debugging
purposes. This is often the same as the value of *query-io*, but need not be.
[Variable]
*terminal-io*
The value of *terminal-io* is ordinarily the stream that connects to the user's
console. Typically, writing to this stream would cause the output to appear on
a display screen, for example, and reading from the stream would accept input
from a keyboard.
It is intended that standard input functions such as read and read-char, when
used with this stream, would cause ``echoing'' of the input into the output
side of the stream. (The means by which this is accomplished are of course
highly implementation-dependent.)
[Variable]
*trace-output*
The value of *trace-output* is the stream on which the trace function prints
its output.
The variables *standard-input*, *standard-output*, *error-output*,
*trace-output*, *query-io*, and *debug-io* are initially bound to synonym
streams that pass all operations on to the stream that is the value of
*terminal-io*. (See make-synonym-stream.) Thus any operations performed on
those streams will go to the terminal.
[change_begin]
X3J13 voted in January 1989 (STANDARD-INPUT-INITIAL-BINDING) to replace the
requirements of the preceding paragraph with the following new requirements:
The seven standard stream variables, *standard-input*, *standard-output*,
*query-io*, *debug-io*, *terminal-io*, *error-output*, and *trace-output*, are
initially bound to open streams. (These will be called the standard initial
streams.)
The streams that are the initial values of *standard-input*, *query-io*,
*debug-io*, and *terminal-io* must support input.
The streams that are the initial values of *standard-output*, *error-output*,
*trace-output*, *query-io*, *debug-io*, and *terminal-io* must support output.
None of the standard initial streams (including the one to which *terminal-io*
is initially bound) may be a synonym, either directly or indirectly, for any of
the standard stream variables except *terminal-io*. For example, the initial
value of *trace-output* may be a synonym stream for *terminal-io* but not a
synonym stream for *standard-output* or *query-io*. (These are examples of
direct synonyms.) As another example, *query-io* may be a two-way stream or
echo stream whose input component is a synonym for *terminal-io*, but its input
component may not be a synonym for *standard-input* or *debug-io*. (These are
examples of indirect synonyms.)
Any or all of the standard initial streams may be direct or indirect synonyms
for one or more common implementation-dependent streams. For example, the
standard initial streams might all be synonym streams (or two-way or echo
streams whose components are synonym streams) to a pair of hidden terminal
input and output streams maintained by the implementation.
Part of the intent of these rules is to ensure that it is always safe to bind
any standard stream variable to the value of any other standard stream variable
(that is, unworkable circularities are avoided) without unduly restricting
implementation flexibility.
[change_end]
No user program should ever change the value of *terminal-io*. A program that
wants (for example) to divert output to a file should do so by binding the
value of *standard-output*; that way error messages sent to *error-output* can
still get to the user by going through *terminal-io*, which is usually what is
desired.
-------------------------------------------------------------------------------
21.2. Creating New Streams
Perhaps the most important constructs for creating new streams are those that
open files; see with-open-file and open. The following functions construct
streams without reference to a file system.
[Function]
make-synonym-stream symbol
make-synonym-stream creates and returns a synonym stream. Any operations on the
new stream will be performed on the stream that is then the value of the
dynamic variable named by the symbol. If the value of the variable should
change or be bound, then the synonym stream will operate on the new stream.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
make-synonym-stream is always a stream of type synonym-stream. Note that the
type of a synonym stream is always synonym-stream, regardless of the type of
the stream for which it is a synonym.
[change_end]
[Function]
make-broadcast-stream &rest streams
This returns a stream that works only in the output direction. Any output sent
to this stream will be sent to all of the streams given. The set of operations
that may be performed on the new stream is the intersection of those for the
given streams. The results returned by a stream operation are the values
resulting from performing the operation on the last stream in streams; the
results of performing the operation on all preceding streams are discarded. If
no streams are given as arguments, then the result is a ``bit sink''; all
output to the resulting stream is discarded.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
make-broadcast-stream is always a stream of type broadcast-stream.
[change_end]
[Function]
make-concatenated-stream &rest streams
This returns a stream that works only in the input direction. Input is taken
from the first of the streams until it reaches end-of-file; then that stream is
discarded, and input is taken from the next of the streams, and so on. If no
arguments are given, the result is a stream with no content; any input attempt
will result in end-of-file.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
make-concatenated-stream is always a stream of type concatenated-stream.
[change_end]
[Function]
make-two-way-stream input-stream output-stream
This returns a bidirectional stream that gets its input from input-stream and
sends its output to output-stream.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
make-two-way-stream is always a stream of type two-way-stream.
[change_end]
[Function]
make-echo-stream input-stream output-stream
This returns a bidirectional stream that gets its input from input-stream and
sends its output to output-stream. In addition, all input taken from
input-stream is echoed to output-stream.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
make-echo-stream is always a stream of type echo-stream.
X3J13 voted in January 1989 (PEEK-CHAR-READ-CHAR-ECHO) to clarify the
interaction of read-char, unread-char, and peek-char with echo streams. (See
the descriptions of those functions for details.)
X3J13 explicitly noted that the bidirectional streams that are the initial
values of *query-io*, *debug-io*, and *terminal-io*, even though they may have
some echoing behavior, conceptually are not necessarily the products of calls
to make-echo-stream and therefore are not subject to the new rules about
echoing on echo streams. Instead, these initial interactive streams may have
implementation-dependent echoing behavior.
[change_end]
[Function]
make-string-input-stream string &optional start end
This returns an input stream. The input stream will supply, in order, the
characters in the substring of string delimited by start and end; after the
last character has been supplied, the stream will then be at end-of-file.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
make-string-input-stream is always a stream of type string-stream.
[change_end]
[old_change_begin]
[Function]
make-string-output-stream
This returns an output stream that will accumulate all output given it for the
benefit of the function get-output-stream-string.
[old_change_end]
[change_begin]
X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to let
make-string-output-stream take an :element-type argument.
[Function]
make-string-output-stream &key :element-type
This returns an output stream that will accumulate all output given it for the
benefit of the function get-output-stream-string.
The :element-type argument specifies what characters must be accepted by the
created stream. If the :element-type argument is omitted, the created stream
must accept all characters.
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
make-string-output-stream is always a stream of type string-stream.
[change_end]
[Function]
get-output-stream-string string-output-stream
Given a stream produced by make-string-output-stream, this returns a string
containing all the characters output to the stream so far. The stream is then
reset; thus each call to get-output-stream-string gets only the characters
since the last such call (or the creation of the stream, if no such previous
call has been made).
[Macro]
with-open-stream (var stream) {declaration}* {form}*
The form stream is evaluated and must produce a stream. The variable var is
bound with the stream as its value, and then the forms of the body are executed
as an implicit progn; the results of evaluating the last form are returned as
the value of the with-open-stream form. The stream is automatically closed on
exit from the with-open-stream form, no matter whether the exit is normal or
abnormal; see close. The stream should be regarded as having dynamic extent.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the stream
created by with-open-stream is always of type file-stream.
[change_end]
[Macro]
with-input-from-string (var string keyword {value}*)
{declaration}* {form}*
The body is executed as an implicit progn with the variable var bound to a
character input stream that supplies successive characters from the value of
the form string. with-input-from-string returns the results from the last form
of the body.
The input stream is automatically closed on exit from the
with-input-from-string form, no matter whether the exit is normal or abnormal.
The stream should be regarded as having dynamic extent.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the stream
created by with-input-from-string is always of type string-stream.
[change_end]
The following keyword options may be used:
:index
The form after the :index keyword should be a place acceptable
to setf. If the with-input-from-string form is exited normally,
then the place will have stored into it the index into the
string indicating the first character not read (the length of
the string if all characters were used). The place is not
updated as reading progresses, but only at the end of the
operation.
:start
The :start keyword takes an argument indicating, in the manner
usual for sequence functions, the beginning of a substring of
string to be used.
:end
The :end keyword takes an argument indicating, in the manner
usual for sequence functions, the end of a substring of string
to be used.
Here is an example of the use of with-input-from-string:
(with-input-from-string (s "Animal Crackers" :index j :start 6)
(read s)) => crackers
As a side effect, the variable j is set to 15.
The :start and :index keywords may both specify the same variable, which is a
pointer within the string to be advanced, perhaps repeatedly by some containing
loop.
[change_begin]
X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
user side effects; see section 7.9.
[change_end]
[old_change_begin]
[Macro]
with-output-to-string (var [string]) {declaration}* {form}*
The body is executed as an implicit progn with the variable var bound to a
character output stream. All output to that stream is saved in a string. This
may be done in one of two ways.
If no string argument is provided, then the value of with-output-from-string is
a string containing all the collected output.
If string is specified, it must be a string with a fill pointer; the output is
incrementally appended to the string, as if using vector-push-extend if the
string is adjustable, and otherwise as if using vector-push. In this case
with-output-to-string returns the results from the last form of the body.
In either case, the output stream is automatically closed on exit from the
with-output-from-string form, no matter whether the exit is normal or abnormal.
The stream should be regarded as having dynamic extent.
[old_change_end]
[change_begin]
X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to let
with-output-to-string take an :element-type argument.
[Macro]
with-output-to-string (var [string [:element-type type]])
{declaration}* {form}*
One may specify nil instead of a string as the string and use the :element-type
argument to specify what characters must be accepted by the created stream. If
no string argument is provided, or if it is nil and no :element-type is
specified, the created stream must accept all characters.
X3J13 voted in October 1988 (WITH-OUTPUT-TO-STRING-APPEND-STYLE) to specify
that if string is specified, it must be a string with a fill pointer; the
output is incrementally appended to the string (as if by use of
vector-push-extend).
In this way output cannot be accidentally lost. This change makes
with-output-to-string behave in the same way that format does when given a
string as its first argument.
X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the stream
created by with-output-to-string is always of type string-stream.
X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
user side effects; see section 7.9.
[change_end]
-------------------------------------------------------------------------------
21.3. Operations on Streams
This section contains discussion of only those operations that are common to
all streams. Input and output is rather complicated and is discussed separately
in chapter 22. The interface between streams and the file system is discussed
in chapter 23.
[Function]
streamp object
streamp is true if its argument is a stream, and otherwise is false.
(streamp x) == (typep x 'stream)
[change_begin]
X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that
streamp is unaffected by whether its argument, if a stream, is open or closed.
In either case it returns true.
[change_end]
[change_begin]
[Function]
open-stream-p stream
X3J13 voted in January 1989 (STREAM-ACCESS) to add the predicate
open-stream-p. It is true if its argument (which must be a stream) is open, and
otherwise is false.
A stream is always created open; it remains open until closed with the close
function. The macros with-open-stream, with-input-from-string,
with-output-to-string, and with-open-file automatically close the created
stream as control leaves their bodies, in effect imposing dynamic extent on the
openness of the stream.
[change_end]
[Function]
input-stream-p stream
This predicate is true if its argument (which must be a stream) can handle
input operations, and otherwise is false.
[Function]
output-stream-p stream
This predicate is true if its argument (which must be a stream) can handle
output operations, and otherwise is false.
[Function]
stream-element-type stream
A type specifier is returned to indicate what objects may be read from or
written to the argument stream, which must be a stream. Streams created by open
will have an element type restricted to a subset of character or integer, but
in principle a stream may conduct transactions using any Lisp objects.
[Function]
close stream &key :abort
The argument must be a stream. The stream is closed. No further input/output
operations may be performed on it. However, certain inquiry operations may
still be performed, and it is permissible to close an already closed stream.
[change_begin]
X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) and revised the vote
in March 1989 to specify that if close is called on an open stream, the stream
is closed and t is returned; but if close is called on a closed stream, it
succeeds without error and returns an unspecified value. (The rationale for not
specifying the value returned for a closed stream is that in some
implementations closing certain streams does not really have an effect on
them-for example, closing the *terminal-io* stream might not ``really'' close
it-and it is not desirable to force such implementations to keep otherwise
unnecessary state. Portable programs will of course not rely on such behavior.)
X3J13 also voted in January 1989 to specify exactly which inquiry functions may
be applied to closed streams:
streamp pathname-host namestring
pathname pathname-device file-namestring
truename pathname-directory directory-namestring
merge-pathnames pathname-name host-namestring
open pathname-type enough-namestring
probe-file pathname-version directory
See the individual descriptions of these functions for more information on how
they operate on closed streams.
X3J13 voted in January 1989 (CLOSE-CONSTRUCTED-STREAM) to clarify the effect
of closing various kinds of streams. First some terminology:
* A composite stream is one that was returned by a call to
make-synonym-stream, make-broadcast-stream, make-concatenated-stream,
make-two-way-stream, or make-echo-stream.
* The constituents of a composite stream are the streams that were given as
arguments to the function that constructed it or, in the case of
make-synonym-stream, the stream that is the symbol-value of the symbol
that was given as an argument. (The constituent of a synonym stream may
therefore vary over time.)
* A constructed stream is either a composite stream or one returned by a
call to make-string-input-stream, make-string-output-stream,
with-input-from-string, or with-output-to-string.
The effect of applying close to a constructed stream is to close that stream
only. No input/output operations are permitted on the constructed stream once
it has been closed (though certain inquiry functions are still permitted, as
described above).
Closing a composite stream has no effect on its constituents; any constituents
that are open remain open.
If a stream created by make-string-output-stream is closed, the result of then
applying get-output-stream-string to the stream is unspecified.
[change_end]
If the :abort parameter is not nil (it defaults to nil), it indicates an
abnormal termination of the use of the stream. An attempt is made to clean up
any side effects of having created the stream in the first place. For example,
if the stream performs output to a file that was newly created when the stream
was created, then if possible the file is deleted and any previously existing
file is not superseded.
[change_begin]
X3J13 voted in January 1989 (STREAM-ACCESS) to add the following accessor
functions for obtaining information about streams.
[Function]
broadcast-stream-streams broadcast-stream
The argument must be of type broadcast-stream. A list of the constituent output
streams (whether open or not) is returned.
[Function]
concatenated-stream-streams concatenated-stream
The argument must be of type concatenated-stream. A list of constituent streams
(whether open or not) is returned. This list represents the ordered set of
input streams from which the concatenated stream may yet read; the stream from
which it is currently reading is first in the list. The list may be empty if no
more streams remain to be read.
[Function]
echo-stream-input-stream echo-stream
echo-stream-output-stream echo-stream
The argument must be of type echo-stream. The function echo-stream-input-stream
returns the constituent input stream; echo-stream-output-stream returns the
constituent output stream.
[Function]
synonym-stream-symbol synonym-stream
The argument must be of type synonym-stream. This function returns the symbol
for whose value the synonym-stream is a synonym.
[Function]
two-way-stream-input-stream two-way-stream
two-way-stream-output-stream two-way-stream
The argument must be of type two-way-stream. The function
two-way-stream-input-stream returns the constituent input stream;
two-way-stream-output-stream returns the constituent output stream.
[Function]
interactive-stream-p stream
X3J13 voted in June 1989 (STREAM-CAPABILITIES) to add the predicate
interactive-stream-p, which returns t if the stream is interactive and
otherwise returns nil. A type-error error is signalled if the argument is not
of type stream.
The precise meaning of interactive-stream-p is implementation-dependent and may
depend on the underlying operating system. The intent is to distinguish between
interactive and batch (background, command-file) operations. Some
characteristics that might distinguish a stream as interactive:
* The stream is connected to a person (or the equivalent) in such a way
that the program can prompt for information and expect to receive input
that might depend on the prompt.
* The program is expected to prompt for input and to support ``normal input
editing protocol'' for that operating environment.
* A call to read-char might hang waiting for the user to type something
rather than quickly returning a character or an end-of-file indication.
The value of *terminal-io* might or might not be interactive.
[Function]
stream-external-format stream
X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to add the function
stream-external-format, which returns a specifier for the
implementation-recognized scheme used for representing characters in the
argument stream. See the :external-format argument to open.
[change_end]
-------------------------------------------------------------------------------